package com.gonsin.gview.logic.services;

import com.gonsin.gview.annotations.GContext;
import com.gonsin.gview.annotations.interfaces.IBatchActionListener;
import com.gonsin.gview.annotations.interfaces.IConfirmActionListener;
import com.gonsin.gview.annotations.interfaces.IDownloadActionListener;
import com.gonsin.gview.annotations.interfaces.IFileActionListener;
import com.gonsin.gview.annotations.model.*;
import com.gonsin.gview.logic.GViewEnvironment;
import com.gonsin.gview.logic.delegate.DelegateBatchActionListenerImpl;
import com.gonsin.gview.logic.delegate.DelegateConfirmActionListenerImpl;
import com.gonsin.gview.logic.delegate.DelegateDownloadListenerImpl;
import com.gonsin.gview.logic.delegate.DelegateUploadActionListenerImpl;
import com.gonsin.gview.logic.exceptions.*;
import com.gonsin.gview.logic.services.download.DownloadManager;
import com.gonsin.gview.logic.utils.SpringUtil;
import com.gonsin.gview.model.GActionModel;
import com.gonsin.gview.model.GViewModel;
import com.gonsin.i18n.logic.T;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 按钮点击事件触发逻辑
 */
@Service
@Slf4j
public class GViewActionServiceImpl {

    private Map<String, GActionModel> actionModelMap = new ConcurrentHashMap<>();

    @Autowired private GViewCoreServiceImpl coreService;
    @Autowired private DownloadManager downloadManager;


//    /**
//     * 触发按钮事件
//     */
//    public void activeButton(HttpServletRequest request, ButtonRequest button) {
//        IButtonAction action = actionMap.get(button.getButtonId());
//        if(action == null){
//            throw new ActionNotFoundException();
//        }
//
//        action.run(request, button);
//    }

    /**
     * 设置文件上传按钮事件
     */
    public void putFileAction(GContext context, String buttonId, Class<? extends IFileActionListener> fileAction) {
        IFileActionListener listener = SpringUtil.getBean(fileAction);
        if(listener == null){
            try {
                listener = fileAction.newInstance();
            } catch (Exception e) {
                log.error(e.toString(), e);
//                throw new CreateActionException(fileAction.getName());
                throw new BaseGViewException(String.format("【%s】无法创建类【%s】",
                        context.getViewName(),
                        fileAction.getName()));
            }
        }
        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
//                throw new ActionRepeatException(context);
                if(GViewEnvironment.THROW_EXCEPTION_WHEN_INIT) {
                    throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个事件",
                            context.getViewName()));
                }

//                throw new BaseGViewException(String.format("类%s，方法名%s，参数类型不支持%s", target.getClass().getName(),
//                        actionMethod.getName(), p.getTypeName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }

    /**
     * 设置批量操作事件
     */
    public void putBatchAction(GContext context, String buttonId, Class<? extends IBatchActionListener> batchAction) {
        IBatchActionListener listener = SpringUtil.getBean(batchAction);
        if(listener == null){
            try {
                listener = batchAction.newInstance();
            } catch (Exception e) {
                log.error(e.toString(), e);
                throw new BaseGViewException(String.format("【%s】绑定了不存在的class【%s】",
                        context.getViewName(), batchAction.getName()));
            }
        }
        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
//                throw new ActionRepeatException(context);
                throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个事件",
                        context.getViewName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }

    /**
     * 设置确认操作事件
     */
    public void putConfirmAction(GContext context, String buttonId, Class<? extends IConfirmActionListener> confirmAction) {
        IConfirmActionListener listener = SpringUtil.getBean(confirmAction);
        if(listener == null){
            try {
                listener = confirmAction.newInstance();
            } catch (Exception e) {
                log.error(e.toString(), e);
                throw new BaseGViewException(String.format("【%s】绑定了不存在的class【%s】",
                        context.getViewName(), confirmAction.getName()));
            }
        }

        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
//                throw new ActionRepeatException(context);
                throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个事件",
                        context.getViewName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }

    /**
     * 设置确认操作事件
     */
    public void putConfirmAction(GContext context, String buttonId, IConfirmActionListener listener) {
        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
//                throw new ActionRepeatException(context);
                throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个事件",
                        context.getViewName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }



    /**
     * 触发批量操作
     */
    public void activeBatch(HttpServletRequest request, HttpServletResponse response, BatchRequest batch) throws Throwable {
        GActionModel actionModel = actionModelMap.get(batch.getButtonId());
        if(actionModel == null || actionModel.getBatchActionListener() == null){
            throw new BaseGViewException(String.format("buttonId【%s】" + T.t("找不到对应的事件"), batch.getButtonId()));
        }
        actionModel.getBatchActionListener().onClick(request, response, batch);
    }



    /**
     * 触发批量操作
     */
    public DownloadResponse activeDownload(HttpServletRequest request, HttpServletResponse response, DownloadRequest downloadRequest) throws Throwable {
        GActionModel actionModel = actionModelMap.get(downloadRequest.getButtonId());
        if(actionModel == null || actionModel.getDownloadActionListener() == null){
            throw new BaseGViewException(String.format("buttonId【%s】" + T.t("找不到对应的事件"), downloadRequest.getButtonId()));
        }
//        return actionModel.getDownloadActionListener().getDownloadUrl(request, response, viewName, buttonId);
        DownloadResponse url = actionModel.getDownloadActionListener().getDownloadUrl(request, response, downloadRequest);
        String downloadId = null;
        if(url.getPurityFile() != null){
            downloadId = downloadManager.putDownloadItem(url.getPurityFile());
        } else if(url.getPurityString() != null){
            downloadId = downloadManager.putDownloadItem(url.getPurityString());
        } else if(url.getPurityInputStream() != null){
            downloadId = downloadManager.putDownloadItem(url.getPurityInputStream());
        }
        if(downloadId != null && !downloadId.equals("")){
            url.setUrl("/api/s11/gview/download/" + downloadId + "/" + url.getFilename());
        }
        return url;
    }


    /**
     * 触发文件上传
     */
    public void activeFile(HttpServletRequest request, HttpServletResponse response, FileRequest fileRequest) throws Throwable {
        GActionModel actionModel = actionModelMap.get(fileRequest.getButtonId());
        if(actionModel == null || actionModel.getFileActionListener() == null){
            throw new BaseGViewException(String.format("buttonId【%s】" + T.t("找不到对应的事件"), fileRequest.getButtonId()));
        }

        // 如果上传的是文件夹，则组合成一个文件


        actionModel.getFileActionListener().onUploadFile(request, response, fileRequest);
    }


    /**
     * 触发确认事件
     */
    public void activeConfirm(HttpServletRequest request, HttpServletResponse response, ConfirmRequest confirmRequest) throws Throwable {
        GActionModel actionModel = actionModelMap.get(confirmRequest.getButtonId());
        if(actionModel == null || actionModel.getConfirmActionListener() == null){
            throw new BaseGViewException(String.format("buttonId【%s】" + T.t("找不到对应的事件"), confirmRequest.getButtonId()));
        }
        IConfirmActionListener actionListener = actionModel.getConfirmActionListener();
        GContext context = new GContext(confirmRequest.getViewName(),
                request, response, confirmRequest.getProps(), false);
        actionListener.onClick(context, confirmRequest.getButtonId(), request, response, confirmRequest.getProps());
    }



    /**
     * 添加@GAction的点击事件
     */
    public void putFileAction(GContext context, String buttonId, String actionName, Class actionService, Method actionMethod) {
        Object obj = SpringUtil.getBean(actionService);
        if(obj == null){
//            throw new ActionClassNotFoundException(context, actionService.getName());
            throw new BaseGViewException(String.format("【%s】绑定了不存在的class【%s】",
                    context.getViewName(), actionService.getName()));
        }
        IFileActionListener listener = new DelegateUploadActionListenerImpl(context, actionName, obj, actionMethod);
        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
//                throw new ActionRepeatException(context);
                throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个点击事件",
                        context.getViewName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }



    /**
     * 添加@GAction的点击事件
     */
    public void putBatchAction(GContext context, String buttonId, Class actionService, Method actionMethod) {
        Object obj = SpringUtil.getBean(actionService);
        if(obj == null){
//            throw new ActionClassNotFoundException(context, actionService.getName());
            throw new BaseGViewException(String.format("【%s】绑定了不存在的class【%s】",
                    context.getViewName(), actionService.getName()));
        }
        IBatchActionListener listener = new DelegateBatchActionListenerImpl(obj, actionMethod);
        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
                throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个点击事件",
                        context.getViewName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }


    /**
     * 添加@GAction的点击事件
     */
    public void putConfirmAction(GContext context, String buttonId, Class actionService, Method actionMethod) {
        Object obj = SpringUtil.getBean(actionService);
        if(obj == null){
//            throw new ActionClassNotFoundException(context, actionService.getName());
            throw new BaseGViewException(String.format("【%s】绑定了不存在的class【%s】",
                    context.getViewName(), actionService.getName()));
        }
        IConfirmActionListener listener = new DelegateConfirmActionListenerImpl(obj, actionMethod);
        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
                throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个点击事件",
                        context.getViewName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }


    /**
     * 根据buttonId获取具体action事件
     * @param buttonId
     * @return
     */
    public GActionModel findActionById(String buttonId) {
        return actionModelMap.get(buttonId);
    }


    /**
     * 设置下载事件
     */
    public void putDownloadAction(GContext context, String buttonId, String actionName, Class actionService, Method actionMethod) {
        Object obj = SpringUtil.getBean(actionService);
        if(obj == null){
//            throw new ActionClassNotFoundException(context, actionService.getName());
            throw new BaseGViewException(String.format("【%s】绑定了不存在的class【%s】",
                    context.getViewName(), actionService.getName()));
        }
        IDownloadActionListener listener = new DelegateDownloadListenerImpl(obj, actionMethod);
        synchronized (this){
            if(actionModelMap.containsKey(buttonId)){
                throw new BaseGViewException(String.format("【%s】某个按钮绑定了多个点击事件",
                        context.getViewName()));
            }
            actionModelMap.put(buttonId, new GActionModel(listener));
        }
    }
}
